package br.com.edoc.gerentes;

import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import br.com.edoc.anotation.Consulta;
import br.com.edoc.anotation.SaveOrUpdate;
import br.com.edoc.entidade.EntidadePadrao;
import br.com.edoc.excecoes.ExceptionApplication;
import br.com.edoc.excecoes.ExceptionValidador;
import br.com.edoc.hibernate.HibernateUtilitario;
import br.com.edoc.validador.ValidadorPadrao;

public class GerentePadraoImpl implements GerentePadrao{


	private Session session;
	
	private Transaction transacao;
	
	private ValidadorPadrao validador;

	@SaveOrUpdate(valida=true)
	public void incluir(EntidadePadrao obj) throws ExceptionApplication,
	ExceptionValidador {

		try{
			getSession().saveOrUpdate(obj);
			this.comit();
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.rowback();
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   

		}
	}
	public void saveObj(EntidadePadrao entidade) throws ExceptionApplication{
		try{
			getSession().saveOrUpdate(entidade);
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
		
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   

		}
	}
	public void updateObj(EntidadePadrao entidade) throws ExceptionApplication{
		try{
			getSession().update(entidade);
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
		
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   

		}
	}

	@SaveOrUpdate(valida=true)
	public void alterar(EntidadePadrao obj) throws ExceptionApplication,
	ExceptionValidador {
		// TODO Auto-generated method stub
		try{
			getSession().saveOrUpdate(obj);
			this.comit();
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.rowback();
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   

		}
	}

	@SaveOrUpdate(valida=false)
	public void deletar(EntidadePadrao obj) throws ExceptionApplication {
		// TODO Auto-generated method stub
		try{
			getSession().delete(obj);
			this.comit();
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.rowback();
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   
		}
	}

	
	@Consulta
	public <T extends EntidadePadrao> List<T> obterListaEntidade(Class<T> classe,EntidadePadrao obj)   throws ExceptionApplication {
		// TODO Auto-generated method stub
		try {
			GerenteHQL gerente = new GerenteHQLImpl();
			return gerente.getQuery(classe, obj);
		} catch (ExceptionApplication e) {
			// TODO Auto-generated catch block
			System.out.print(e);
			throw new ExceptionApplication(e.getMessage());
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   
		}
	}

	
	@Consulta
	public <T extends EntidadePadrao> List<T> obterListaEntidade(Class<T> classe,EntidadePadrao obj,String ordenador)  
			throws ExceptionApplication {
		// TODO Auto-generated method stub
		try {
			GerenteHQL gerente = new GerenteHQLImpl();
			return gerente.getQuery(classe, obj,ordenador);
		} catch (ExceptionApplication e) {
			// TODO Auto-generated catch block
			System.out.print(e);
			throw new ExceptionApplication(e.getMessage());
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   
		}
	}


	@Consulta
	public <T extends EntidadePadrao>  List<T> obterListaEntidade(Class<T> classe,EntidadePadrao obj,Integer quantMaxResult) throws ExceptionApplication {
		// TODO Auto-generated method stub
		try {
			GerenteHQL gerente = new GerenteHQLImpl();
			return gerente.getQuery(classe, obj,quantMaxResult);
		} catch (ExceptionApplication e) {
			// TODO Auto-generated catch block
			System.out.print(e);
			throw new ExceptionApplication(e.getMessage());
		}catch (HibernateException e) {
			// TODO: handle exception
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   
		}
	}

	
	@Consulta
	public <T extends EntidadePadrao> List<T> obterListaEntidade(Class<T> classe,EntidadePadrao obj,String ordenador,Integer quantMaxResult) throws ExceptionApplication {
		// TODO Auto-generated method stub
		try {
			GerenteHQL gerente = new GerenteHQLImpl();
			return gerente.getQuery(classe, obj,ordenador,quantMaxResult);
		} catch (ExceptionApplication e) {
			// TODO Auto-generated catch block
			System.out.print(e);
			throw new ExceptionApplication(e.getMessage());
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   
		}
	}

	
	@Consulta
	public <T extends EntidadePadrao> EntidadePadrao obterEntidadeForId(Class<T> obj,Integer id) throws ExceptionApplication {
		// TODO Auto-generated method stub
		try{
			EntidadePadrao query = (EntidadePadrao) getSession().load(obj, id);
			Hibernate.initialize(query);
			return query;
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.close();

			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   
		}
	}

	public static <T> List<T> listAndCast(Query q) {
		@SuppressWarnings("unchecked")
		List<T> list = q.list();
		return list;
	}


	
	public Session getSession() {
		if(session ==null   || !session.isOpen()){
			setSession(HibernateUtilitario.currentSession());
		}	
		
		return session;
	}

	public void setSession(Session session) {
		this.session = session;
	}

	public Transaction getTransacao() {
		if(transacao==null || !transacao.isActive()){
			setTransacao(getSession().beginTransaction());
		}
		return transacao;
	}

	public void setTransacao(Transaction transacao) {
		this.transacao = transacao;
	}

	public void comit(){
		getTransacao().commit();
	}

	public void rowback(){
		getTransacao().rollback();
	}

	public void close(){
		getSession().close();
	}
	public ValidadorPadrao getValidador() {
		return validador;
	}
	public void setValidador(ValidadorPadrao validador) {
		this.validador = validador;
	}
	
}